﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Crossroad.Utils.Extensions
{
    public static class JObjectExt
    {
        public static T Get<T>(this JObject input, string props)
        {
            var to = default(T);
            if (input.IsNull())
                return to;
            if (props.IsNull())
                return to;

            object obj = input;
            var arrProp = props.Split('.');
            foreach (var prop in arrProp)
            {
                if (obj.IsNull())
                    return to;

                if(obj is JObject)
                    obj = ((JObject)obj).GetValue(prop);
                else if (obj is JToken)
                    obj = ((JToken) obj)[prop];
                else
                    obj = null;
            }

            try
            {
                return to = (T) (obj as JValue).Value;
            }
            catch
            {
                return default(T);
            }
        }

        public static object Get(this JObject input, string props)
        {
            if (input.IsNull())
                return null;
            if (props.IsNull())
                return null;

            object obj = input;
            var arrProp = props.Split('.');
            foreach (var prop in arrProp)
            {
                if (obj.IsNull())
                    return null;

                if(obj is JObject)
                    obj = ((JObject)obj).GetValue(prop);
                else if (obj is JToken)
                    obj = ((JToken) obj)[prop];
                else
                    obj = null;
            }

            if (obj.IsNull()) return null;

            return obj is JValue ? (obj as JValue)?.Value : obj;
        }

        public static T Get<T>(this JToken input, string prop)
        {
            var to = default(T);
            if (input == null)
                return to;

            try
            {
                return to = (T) (input[prop] as JValue).Value;
            }
            catch
            {
                return default(T);
            }
        }

        public static object Get(this JToken input, string prop)
        {
            if (input == null)
                return null;

            var value = input[prop];

            return value is JValue ? (value as JValue)?.Value : value;
        }

        public static void CopyTo(this JObject input, object target, bool underline = false)
        {
            var outType = target.GetType();
            foreach (var itemOut in outType.GetProperties())
            {
                var value = input.Get(underline ? itemOut.Name.ToUnderline() : itemOut.Name);
                if (value.NotNull())
                    itemOut.SetValue(target, value.ChangeType(itemOut.PropertyType));
            }
        }

        public static void CopyTo(this JToken input, object target, bool underline)
        {
            var outType = target.GetType();
            foreach (var itemOut in outType.GetProperties())
            {
                var value = input.Get(underline ? itemOut.Name.ToUnderline() : itemOut.Name);
                if (value.NotNull())
                    itemOut.SetValue(target, value.ChangeType(itemOut.PropertyType));
            }
        }


    }
}
